﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Site3AI.Models;

namespace M3AI.Services
{
    public partial class Services
    {
        public Site3AIEntities DB { get; set; }
        public aspnet_Users SiteUser { get; set; }
        public _SiteBaseController ControllerContext { get; set; }
        public static int DefaultPageSize = 25;
        public static int MobilePageSize = 10;
        //public int DefaultPageSize
        //{
        //    get { return this.DefaultPageSize; }
        //}

        public DateTime Now
        {
            get
            {
                return MvcApplication.Now;
            }
        }

        public ListViewModel<CommonSearchValues, IQueryable<TimelineItem>> MyTimelineSource(ListViewModel<CommonSearchValues, IQueryable<TimelineItem>> m) 
        {
            if (null == m || null == m.SearchFrom)
            {
                m = new ListViewModel<CommonSearchValues, IQueryable<TimelineItem>>()
                {
                    PageSize = M3AI.Services.Services.DefaultPageSize ,
                    SearchFrom = new CommonSearchValues(),
                    SearchTo = new CommonSearchValues()
                };
            }
            var src=m.SearchFrom.V1;
            var type=m.SearchFrom.V2; 

            IQueryable<TimelineItem> rd=null;
            if(string.IsNullOrEmpty(src)|| src=="UserMemo"){
                var d = DB.UserMemoes.Where(v => v.UserID == SiteUser.UserId);
                if (!string.IsNullOrEmpty(type)) { var w = type.Trim(); d = d.Where(v => v.Title.Contains(w) || v.MemoText.Contains(w) || (v.Recuper != null && (v.Recuper.Hospital.HospName.Contains(w) || v.Recuper.Hospital.HospCode.Contains(w)))); }
                var ti=d.Select(v=>new TimelineItem(){ Source=src, Title="备忘录 "+v.Title, Text=(null==v.Recuper)?"私人记录":(v.Recuper.Hospital.HospCode+v.Recuper.BingQu.Title+v.Recuper.EnHospDay.ToString("yyyy年M月"))+v.MemoText, TimelineTime=v.Timemark, Type=v.Title, Keys=new{id=v.ID}});
                if(null==rd)rd=ti;
                else rd=rd.Union(ti);
            }
            if(string.IsNullOrEmpty(src)||src=="QizSessionJcd"){
                var d = DB.QizSessions.Where(v => v.UserID == SiteUser.UserId);
                if (!string.IsNullOrEmpty(type)) { var w = type.Trim(); d = d.Where(v => v.QizSubject.Title.Contains(w) ); }
                var ti=d.Select(v=>new TimelineItem(){ Source=src, Title="检查单 "+v.QizSubject.Title+" "+v.SessionAutoEvaluation, Text=v.Recuper.Hospital.HospCode+v.Recuper.BingQu.Title+v.Timemark.ToString("yyyy年M月"), TimelineTime=v.CreationTime, Type=type, Keys=new{id=v.ID,PreviewOnly="True"}});
                if(null==rd)rd=ti;
                else rd=rd.Union(ti);
            }
            if(string.IsNullOrEmpty(src)||src=="Recuper"){
                var d = DB.Recupers.Where(v => v.UserID == SiteUser.UserId);
                //if (!string.IsNullOrEmpty(type)) { var w = type.Trim(); d = d.Where(v => v.QizSubject.Title.Contains(w) ); }
                var ti=d.Select(v=>new TimelineItem(){ Source=src, Title="住院 "+v.Hospital.HospCode+v.BingQu.Title+v.Department.DepName, Text=v.ZhenDuanS+";"+v.ShouShuS, TimelineTime=v.EnHospDay, Type=type, Keys=new{id=v.RecuperID}});
                if(null==rd)rd=ti;
                else rd=rd.Union(ti);
                DateTime mintime=new DateTime(1900,1,1);
                var ti2=d.Where(v=>v.DeHospDay>mintime).Select(v=>new TimelineItem(){ Source=src, Title="出院 "+v.Hospital.HospCode+v.BingQu.Title+v.Department.DepName, Text=v.ZhenDuanS+";"+v.ShouShuS, TimelineTime=v.DeHospDay, Type=type, Keys=new{id=v.RecuperID}});
                if(null==rd)rd=ti;
                else rd=rd.Union(ti2);
            }

            if(string.IsNullOrEmpty(src)||src=="QizSession"){
                var d = DB.QizSessions.Where(v => v.UserID == SiteUser.UserId);
                if (!string.IsNullOrEmpty(type)) { var w = type.Trim(); d = d.Where(v => v.QizSubject.Title.Contains(w) ); }
                var ti=d.Select(v=>new TimelineItem(){ Source=src, Title="随访填报 "+v.QizSubject.Title+" "+v.SessionAutoEvaluation, Text=v.Recuper.Hospital.HospCode+v.Recuper.BingQu.Title+v.Timemark.ToString("yyyy年M月"), TimelineTime=v.CreationTime, Type=type, Keys=new{id=v.ID,PreviewOnly="True"}});
                if(null==rd)rd=ti;
                else rd=rd.Union(ti);
            }


            if (!string.IsNullOrEmpty(m.SearchFrom.V2)) { var w = DateTime.Parse(m.SearchFrom.V2); rd = rd.Where(v => v.TimelineTime >= w); }
            if (!string.IsNullOrEmpty(m.SearchTo.V2)) { var w = DateTime.Parse(m.SearchTo.V2).AddDays(1); rd = rd.Where(v => v.TimelineTime <= w); }


            m.ItemCount = rd.Count();
            m.PageCount = (int)Math.Ceiling((double)rd.Count() / m.PageSize);
            rd = rd.OrderByDescending(v => v.TimelineTime);
            m.Data = rd;
            return m;
        }
        public QizSession QizSessionEditInner_Get(string SubjectID, string ID, string RefAttID)
        {
            if (string.IsNullOrWhiteSpace(ID))
            {
                bool hasRefItem = false;
                QizSessionDetail di = null;
                if (!string.IsNullOrEmpty(RefAttID))
                {
                    di = DB.QizSessionDetails.First(v => v.ID == RefAttID);
                    hasRefItem = true;
                }

                var sm = DB.QizSubjects.Where(v => v.ID == SubjectID).First();

                var m = new QizSession() { QizSubject = sm,QizSubjectID=sm.ID, ID = "-1", Timemark = DateTime.MinValue, CreationTime = Now };
                if (hasRefItem) m.PID = di.QizSessionID;
                foreach (var item in sm.QizSubjectDefines)
                {
                    var qd = new QizSessionDetail();
                    qd.ID = item.ID;
                    qd.QizSession = m;
                    qd.QizSubjectDefine = item;
                    if (hasRefItem && item.QizItem.Type == "206")
                    {//如果引用了某个附件,而且有附件字段，则(现在只)把引用附件放到自己的附件位。
                        qd.UserValue = di.UserValue;
                        m.PID = di.QizSessionID;
                        m.RecuperID = di.QizSession.RecuperID;
                        hasRefItem = false;
                    }
                    m.QizSessionDetails.Add(qd);

                }

                return m;

            }
            else
            {
                var m = DB.QizSessions.Where(v => v.ID == ID).FirstOrDefault();
                return m;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tm"></param>
        /// <returns>item1 is model,item2 is success or haserror.
        /// when false(mean haserror), use return view(item2)</returns>
        public Tuple<QizSession, bool> QizSessionEditInner_Post(QizSession tm, string userID = null)
        {
            string[] imgExts = { ".png", ".jpg", ".gif", ".jpeg" };
            string EVALESULT_FINE = "正常", EVALESULT_BAD = "异常";
            bool sessionHasBadEvalResult = false;
            bool haserror = false;

            tm.Timemark = tm.Timemark.Date;

            QizSession m = null;

            bool isnew = string.IsNullOrWhiteSpace(tm.ID) || tm.ID == "-1";
            if (isnew)
            {
                var qiz = DB.QizSubjects.Where(v => v.ID == tm.QizSubjectID).First();

                QizSession ParentSession = null;
                if (!string.IsNullOrEmpty(tm.PID))
                {
                    ParentSession = DB.QizSessions.FirstOrDefault(v => v.ID == tm.PID);
                }

                Recuper recuper = null;

                if (ParentSession != null)
                {
                    recuper = ParentSession.Recuper;
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(userID) || userID == "-1")
                    {
                        recuper = qiz.QizSubjectObjForDoctors.FirstOrDefault(s => s.Recuper.UserID == SiteUser.UserId && s.QizSubjectID == tm.QizSubjectID).Recuper;
                    }
                    else
                    {
                        recuper = qiz.QizSubjectObjForDoctors.FirstOrDefault(s => s.Recuper.RecuperID == userID && s.QizSubjectID == tm.QizSubjectID).Recuper;
                    }

                }

                m = tm;
                m.ID = DB.NewID();
                m.Timemark = tm.Timemark;
                m.CreationTime = Now;
                m.SubmitSrc = "网络";
                m.aspnet_Users = recuper.User;
                m.DoctorID = null;
                m.QizSubject = qiz;
                m.RecuperID = recuper.RecuperID;
                m.Recuper = recuper;
                m.UnRead = true;
                m.PID = tm.PID;

                foreach (var item in qiz.QizSubjectDefines)
                {
                    var qd = new QizSessionDetail();
                    qd.ID = item.ID;
                    qd.QizSession = m;
                    qd.QizSubjectDefine = item;
                    m.QizSessionDetails.Add(qd);
                }
            }
            else
            {
                m = DB.QizSessions.Where(v => v.ID == tm.ID).First();
            }

            m.Timemark = tm.Timemark;

            if (m.Timemark.Year < 2001 || m.Timemark > MvcApplication.Now.Date)
            {
                ControllerContext.ModelState.AddModelError("timemarkerror", "检查时间必须填写正确");
                haserror = true;
            }

            foreach (var item in m.QizSessionDetails)
            {
                var itemkey = "QSD." + item.ID;
                var rawuserval = ControllerContext.ValueProvider.GetValue(itemkey) as System.Web.Mvc.ValueProviderResult;
                if (null == rawuserval)
                {
                    itemkey = "QSD." + item.QizSubjectDefine.ID;
                    rawuserval = ControllerContext.ValueProvider.GetValue(itemkey) as System.Web.Mvc.ValueProviderResult;
                }

                //itemkey = Request.Form.AllKeys.Contains(itemkey) ? itemkey : "QSD." + item.QizSubjectDefine.ID;

                var qizdefine = item.QizSubjectDefine != null ? item.QizSubjectDefine : DB.QizSubjectDefines.First(v => v.ID == item.QizSubjectDefID);
                var qizitem = qizdefine.QizItem;
                var typeval = item.QizSubjectDefine.QizItem.TypeRef.OptionValue;
                var userval = rawuserval == null ? null : rawuserval.AttemptedValue;// Request.Form[itemkey];
                string userselval = null;
                string itemAutoEvalResult = null;

                if (string.IsNullOrEmpty(userval))//处理空值的必填项问题
                {
                    if (qizitem.Type != "207" && !qizitem.SpecialItem && qizitem.RequiredItem && string.IsNullOrEmpty(qizdefine.ParentSubjDefID))
                    {
                        ControllerContext.ModelState.AddModelError("nullerror_" + item.ID, qizitem.Title);
                        haserror = true;
                    }
                }
                if (typeval == "4" || typeval == "5") //单选、复选
                {
                    #region 单选、复选
                    userselval = userval;
                    userval = null;
                    if (!string.IsNullOrWhiteSpace(userselval))
                    {
                        var selvs = userselval.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        if (string.IsNullOrEmpty(item.QizSubjectDefine.ThresholdLow))
                        {
                            itemAutoEvalResult = null;
                        }
                        else
                        {
                            var normals = item.QizSubjectDefine.ThresholdLow.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            if (item.QizSubjectDefine.QizItem.TypeRef.OptionValue == "4")
                            {
                                itemAutoEvalResult = selvs.Any(s => normals.Contains(s)) ? null : "异常";
                            }
                            if (item.QizSubjectDefine.QizItem.TypeRef.OptionValue == "5")
                            {
                                bool islower = normals.Any(a => selvs.Any(s => s == a));
                                bool isUp = selvs.Any(s => normals.Contains(s));
                                itemAutoEvalResult = (islower && isUp) ? null : "异常";
                            }
                        }
                        //if (typeval == "4")
                        //{
                        //    itemAutoEvalResult = (string.IsNullOrEmpty(item.QizSubjectDefine.ThresholdLow) || item.QizSubjectDefine.ThresholdLow.Contains(userselval + ",")) ? null : "异常";

                        //}
                        //else
                        //{
                        //    itemAutoEvalResult = (string.IsNullOrEmpty(item.QizSubjectDefine.ThresholdLow) || item.QizSubjectDefine.ThresholdLow == userselval) ? null : "异常";
                        //}
                        var uservarray = userselval.Split(',');
                        userval = string.Join(";", item.QizSubjectDefine.QizItem.EnumDefine.EnumValues.Where(v => uservarray.Contains(v.EnumValID)).Select(v => v.OptionTitle).ToArray());
                    }

                    item.UserValue = userval;
                    item.UserSelValue = userselval;
                    #endregion
                }
                else if (typeval == "6")//附件、图片
                {
                    #region 附件、图片
                    var wf = ControllerContext.Request.Files[itemkey];
                    //(rawuserval.RawValue as HttpPostedFileBase[]).Length
                    if (wf != null && !string.IsNullOrEmpty(wf.FileName))
                    {
                        using (var store = StorageLib.StorageFactory.GetDefaultStorageProvider())
                        {
                            if (!string.IsNullOrEmpty(item.UserValue))//有新内容后，会尝试清理上次的数据。
                            {
                                //fn = ControllerContext.Server.MapPath("~/App_Data/FileDB/" + item.UserValue);
                                var oldfn = "/FileDB/" + item.UserValue;
                                try
                                {
                                    store.DeleteFile(oldfn);
                                }
                                catch { }
                                try
                                {
                                    store.DeleteFile(oldfn + ".thumb" + System.IO.Path.GetExtension(item.UserValue));
                                }
                                catch { }
                            }
                            //处理新数据
                            var ext = System.IO.Path.GetExtension(wf.FileName);
                            bool isImg = imgExts.Contains(ext, StringComparer.CurrentCultureIgnoreCase);

                            userval = DB.NewID() + ext;
                            var fn = "/FileDB/" + userval;

                            if (!isImg)
                            {
                                haserror = true;
                                ControllerContext.ModelState.AddModelError("formaterror_" + item.ID, qizitem.Title);
                            }
                            else
                            {
                                var webimg = new System.Web.Helpers.WebImage(wf.InputStream);
                                if (null == webimg)
                                {
                                    haserror = true;
                                    ControllerContext.ModelState.AddModelError("formaterror_" + item.ID, qizitem.Title);
                                }
                                else
                                {
                                    if (webimg.Width > 1900 || webimg.Height > 1900) webimg.Resize(1900, 1900, true, true);
                                    store.PutData(fn, webimg.GetBytes());
                                    if (webimg.Width > 300 || webimg.Height > 300) webimg.Resize(300, 300, true, true);
                                    store.PutData(fn + ".thumb" + ext, webimg.GetBytes());
                                }
                            }
                            item.UserValue = userval;
                        }
                    }
                    else
                    {
                        item.UserValue = ControllerContext.Request[itemkey + ".keep"];
                    }
                    #endregion
                }
                else if (typeval == "2")
                {
                    #region 数值
                    if (string.IsNullOrEmpty(userval))
                    {
                        item.UserValue = string.Empty;
                    }
                    else
                    {
                        double v = 0;
                        if (double.TryParse(userval, out v))
                        {
                            ControllerContext.ModelState.AddModelError("formaterror_" + item.ID, qizitem.Title);
                        }

                        double vl = double.MinValue, vh = double.MaxValue;

                        if (double.TryParse(item.QizSubjectDefine.ThresholdLow, out vl)
                            && double.TryParse(item.QizSubjectDefine.ThresholdHight, out vh))//如果有阀值，则判定阀值
                        {
                            itemAutoEvalResult = (v >= vl && v <= vh) ? null : EVALESULT_BAD;
                        }
                        item.UserValue = userval;
                    }
                    #endregion
                }
                else
                { //other....text...datetime same as text.
                    item.UserValue = userval;
                }
                //将错误的值设为空（主要是医生补录时，修改父项导致结果计算错误）
                //if (item.QizSubjectDefine.ParentSubjDefID != null)
                //{
                //    var parentValue = m.QizSessionDetails.FirstOrDefault(s => s.QizSubjectDefine.ID == item.QizSubjectDefine.ParentSubjDefID);
                //    if (parentValue != null && parentValue.UserSelValue != item.QizSubjectDefine.ParentSubjDefVals)
                //    {
                //        //m.QizSessionDetails.Remove(sItem);
                //        item.UserSelValue = null;
                //        item.UserValue = null;
                //    }
                //}
                if (string.IsNullOrEmpty(userval)) itemAutoEvalResult = null;
                item.ValueAutoEvaluation = itemAutoEvalResult;

                if (!sessionHasBadEvalResult && itemAutoEvalResult != null) sessionHasBadEvalResult = true;
            }
            m.SessionAutoEvaluation = sessionHasBadEvalResult ? EVALESULT_BAD : EVALESULT_FINE;


            if (haserror)
            {
                ControllerContext.ViewBag.ForceEdit = true;

                //ModelState.AddModelError("haserror", "部分内容填写不正确，例如必填项为填写；或错误的指标值。请修改后重新提交。");
                return (new Tuple<QizSession, bool>(m, false));
            }

            if (isnew)
            {
                foreach (var qsditem in m.QizSessionDetails)
                {
                    qsditem.ID = DB.NewID();
                }

                DB.QizSessions.Add(m);
            }
            ProcSF36(m);//try proc sf 36
            DB.SaveChanges();
            return new Tuple<QizSession, bool>(m, true);
        }

        private void ProcSF36(QizSession m)
        {
            //204 is 单选
            var tempvs = m.QizSessionDetails.Where(v => v.UserSelValue != null && v.QizSubjectDefine.QizItem.Type == "204" && v.EnumValue.SF36Value >= 1)
                .Select(v => new { v.EnumValue.EnumDefine.SF36TYPE, v.EnumValue.SF36Value }).GroupBy(v => v.SF36TYPE).ToList();
            var vs = tempvs.Select(g => new Tuple<string, double>(g.Key, g.Sum(t => t.SF36Value)));

            foreach (var g in vs)
            {
                var sdforg = m.QizSessionDetails.FirstOrDefault(v => v.QizSubjectDefine.QizItem.Format == g.Item1);
                if (null != sdforg)
                {
                    //PF RP BP GH VI SF RE MH HT
                    if (g.Item1 == "PF") { sdforg.UserValue = Math.Round((g.Item2 - 10) / 20 * 100).ToString(); }
                    else if (g.Item1 == "RP") { sdforg.UserValue = Math.Round((g.Item2 - 4) / 4 * 100).ToString(); }
                    else if (g.Item1 == "BP") { sdforg.UserValue = Math.Round((g.Item2 - 2) / 10 * 100).ToString(); }
                    else if (g.Item1 == "GH") { sdforg.UserValue = Math.Round((g.Item2 - 5) / 20 * 100).ToString(); }
                    else if (g.Item1 == "VI") { sdforg.UserValue = Math.Round((g.Item2 - 4) / 20 * 100).ToString(); }
                    else if (g.Item1 == "SF") { sdforg.UserValue = Math.Round((g.Item2 - 2) / 8 * 100).ToString(); }
                    else if (g.Item1 == "RE") { sdforg.UserValue = Math.Round((g.Item2 - 3) / 3 * 100).ToString(); }
                    else if (g.Item1 == "MH") { sdforg.UserValue = Math.Round((g.Item2 - 5) / 25 * 100).ToString(); }
                    else if (g.Item1 == "HT") { sdforg.UserValue = Math.Round((g.Item2)).ToString(); }
                }
            }
        }

        /// <summary>
        /// return tuple of haserror,new imagekey
        /// </summary>
        /// <param name="itemkey"></param>
        /// <param name="oldimgkey"></param>
        /// <returns></returns>
        public Tuple<bool, string> SaveRequestImage(string itemkey, string oldimgkey)
        {
            string userval = null;
            bool haserror = false;
            #region 附件、图片
            string[] imgExts = { ".png", ".jpg", ".gif", ".jpeg" };

            var wf = ControllerContext.Request.Files[itemkey];
            //(rawuserval.RawValue as HttpPostedFileBase[]).Length
            if (wf != null && !string.IsNullOrEmpty(wf.FileName))
            {
                using (var store = StorageLib.StorageFactory.GetDefaultStorageProvider())
                {
                    if (!string.IsNullOrEmpty(oldimgkey))//有新内容后，会尝试清理上次的数据。
                    {
                        //fn = ControllerContext.Server.MapPath("~/App_Data/FileDB/" + item.UserValue);
                        var oldfn = "/FileDB/" + oldimgkey;
                        try
                        {
                            store.DeleteFile(oldfn);
                        }
                        catch { }
                        try
                        {
                            store.DeleteFile(oldfn + ".thumb" + System.IO.Path.GetExtension(oldimgkey));
                        }
                        catch { }
                    }
                    //处理新数据
                    var ext = System.IO.Path.GetExtension(wf.FileName);
                    bool isImg = imgExts.Contains(ext, StringComparer.CurrentCultureIgnoreCase);

                    userval = DB.NewID() + ext;
                    var fn = "/FileDB/" + userval;

                    if (!isImg)
                    {
                        haserror = true;
                    }
                    else
                    {
                        var webimg = new System.Web.Helpers.WebImage(wf.InputStream);
                        if (null == webimg)
                        {
                            haserror = true;
                        }
                        else
                        {
                            if (webimg.Width > 1900 || webimg.Height > 1900) webimg.Resize(1900, 1900, true, true);
                            store.PutData(fn, webimg.GetBytes());
                            if (webimg.Width > 300 || webimg.Height > 300) webimg.Resize(300, 300, true, true);
                            store.PutData(fn + ".thumb" + ext, webimg.GetBytes());
                        }
                    }
                }
            }
            else
            {
                userval = ControllerContext.Request[itemkey + ".keep"];
            }
            return new Tuple<bool, string>(haserror, userval);
            #endregion
        }

    }
}